home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 May (DVD) / Macworld Resource DVD May 2003.toast / Data / Software / Bonus / Programming / revolutionosx.sit / Revolution 1.1.1 / External SDK / external.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-12-21  |  23.1 KB  |  846 lines  |  [????/????]

  1. /********************************************/
  2. /*    Copyright 1997 MetaCard Corporation   */
  3. /*    This source code may be used as a     */
  4. /*    template for building external        */
  5. /*    processes for use with Rev or MC.     */
  6. /*    All Other Rights Reserved             */
  7. /********************************************/
  8. /*
  9.   MetaCard template for external commands and functions
  10. */
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <math.h>
  15. #ifdef X11
  16. #include <sys/time.h>
  17. #include <values.h>
  18.  
  19. #ifdef SELECT
  20. #ifndef LINUX
  21. /* some systems don't have select.h and/or stream.h.  If yours doesn't
  22.    delete the offending #include */
  23. #include <sys/select.h>
  24. #include <sys/stream.h>
  25. #endif
  26. #else
  27. #include <poll.h>
  28. #endif
  29. #include <X11/Xlib.h>
  30. #elif defined WIN32
  31. #include <time.h>
  32. #include <windows.h>
  33. #elif defined MACOS
  34. #include <Quickdraw.h>
  35. #include <QDOffscreen.h>
  36. #endif
  37. #include "XCmdGlue.h"
  38. #include "external.h"
  39.  
  40. /*
  41.  * This global table has one entry per XCMD/XFCN.
  42.  * The first entry is the name of the handler
  43.  * The second entry is the type (XCOMMAND or XFUNCTION)
  44.  * The third entry is a space for the atom (used by MetaCard)
  45.  * The fourth entry is the name of the 'C' function to call
  46.  * The fifth entry is a callback called if the user aborts
  47.  * Note that the last entry in the table is a NULL entry
  48.  * which is used to measure the size of the table.
  49.  */
  50.  
  51. Xternal Xtable[] = {
  52. {"xgetvar", XFUNCTION, 0, XGetVar, XCabort},
  53. {"xsetvar", XCOMMAND, 0, XSetVar, XCabort},
  54. {"xsetarray", XCOMMAND, 0, XSetArray, XCabort},
  55. {"xgetarray", XFUNCTION, 0, XGetArray, XCabort},
  56. {"convolve", XCOMMAND, 0, XConvolve, XCabort},
  57. {"sprintf", XCOMMAND, 0, XCsprintf, XCabort},
  58. {"xatan2", XFUNCTION, 0, XFatan2, XCabort},
  59. {"callbacktests", XCOMMAND, 0, XCcallbacktests, XCabort},
  60. {"life_init", XFUNCTION, 0, XFlife_init, XCabort},
  61. {"life_create", XCOMMAND, 0, XClife_create, XCabort},
  62. {"life_delay", XCOMMAND, 0, XClife_delay, XCabort},
  63. {"life_cease", XCOMMAND, 0, XClife_cease, XCabort},
  64. {"", XNONE, 0, NULL, NULL}
  65. };
  66.  
  67. /*
  68.  * This string identifies this external to the engine
  69.  */
  70. char Xname[] = "Template Xternals";
  71.  
  72. /*
  73.  * local variables
  74.  */
  75. #define GRID_SIZE 40
  76. #define CELL_SIZE 8
  77. static char g1[GRID_SIZE + 2][GRID_SIZE + 2];
  78. static char g2[GRID_SIZE + 2][GRID_SIZE + 2];
  79. static char (*oldgrid)[GRID_SIZE + 2];
  80. static char (*newgrid)[GRID_SIZE + 2];
  81. #if defined X11
  82. static GC gc;
  83. static Pixmap pm;
  84. static unsigned long livecolor;
  85. static unsigned long deadcolor;
  86. #elif defined WIN32
  87. static HBITMAP bm;
  88. static HBITMAP oldbitmap;
  89. static HDC memhdc;
  90. static HBRUSH livebrush; //handle to red color brush
  91. static HBRUSH deadbrush; //handle to gray color brush
  92. static HBRUSH oldbrush;  //old brush
  93. #elif defined MACOS
  94. static GWorldPtr gw;
  95. static RGBColor livecolor;
  96. static RGBColor deadcolor;
  97. static Rect rect;
  98. static CGrafPtr oldport;
  99. static GDHandle olddevice;
  100. #endif
  101.  
  102.  
  103. #ifdef __STDC__
  104. void XGetVar(char *args[], int nargs, char **retstring,
  105.            Bool *pass, Bool *error)
  106. #else
  107. void XGetVar(args, nargs, retstring, pass, error)
  108.      char *args[];
  109.      int nargs;
  110.      char **retstring;
  111.      Bool *pass;
  112.      Bool *error;
  113. #endif
  114. {
  115.     int retvalue;
  116.     char *key = NULL;
  117.     char *retstr = NULL;
  118.     *pass = False;
  119.     *error = False;
  120.     if (nargs == 2){
  121.         MCstring val = {NULL,0};
  122.             key = args[1];
  123.         GetVariableEx(args[0],key,&val,&retvalue);
  124.         if (val.sptr != NULL){
  125.             retstr = malloc(val.length+1);
  126.             retstr[val.length] = '\0';
  127.             memcpy(retstr,val.sptr,val.length);
  128.         }
  129.     }
  130.     if (retstr == NULL)
  131.      retstr = calloc(1, 1);
  132.     *retstring = retstr;
  133. }
  134.  
  135. #ifdef __STDC__
  136. void XSetVar(char *args[], int nargs, char **retstring,
  137.            Bool *pass, Bool *error)
  138. #else
  139. void XSetVar(args, nargs, retstring, pass, error)
  140.      char *args[];
  141.      int nargs;
  142.      char **retstring;
  143.      Bool *pass;
  144.      Bool *error;
  145. #endif
  146.      {
  147.     int retvalue;
  148.     char *key = NULL;
  149.     char *retstr = NULL;
  150.     *pass = False;
  151.     *error = False;
  152.     if (nargs == 3){
  153.         MCstring tval;
  154.         tval.sptr = args[2];
  155.         tval.length = strlen(args[2]);
  156.                 key = args[1];
  157.             SetVariableEx(args[0],key,&tval,&retvalue);
  158.     }
  159.     if (retstr == NULL)
  160.         retstr = calloc(1, 1);
  161.     *retstring = retstr;
  162. }
  163.  
  164. #ifdef __STDC__
  165. void XSetArray(char *args[], int nargs, char **retstring,
  166.            Bool *pass, Bool *error)
  167. #else
  168. void XSetArray(args, nargs, retstring, pass, error)
  169.      char *args[];
  170.      int nargs;
  171.      char **retstring;
  172.      Bool *pass;
  173.      Bool *error;
  174. #endif
  175. {
  176.   int retvalue;
  177.   char *retstr = NULL;
  178.   char **keys = NULL;
  179.   int nelements = 0;
  180.   *pass = False;
  181.   *error = False;
  182.   if (nargs >= 2)
  183.     {
  184.       char *tptr = args[1];
  185.       char *lastptr = NULL;
  186.       char *keyptr = NULL;
  187.       MCstring *tstrings;
  188.       Bool usekeys = False;
  189.       int count = 1;
  190.       if (nargs == 3 && (strncmp(args[2],"TRUE",4) == 0))
  191.     usekeys = True;
  192.       do{
  193.     if (*tptr == '\n')
  194.       count++;
  195.       }while(*++tptr);
  196.       if (usekeys){
  197.     keys = (char **)malloc(sizeof(char *)*count);
  198.     memset(keys,0,sizeof(char *)*count);
  199.       }
  200.       tstrings = (MCstring *)malloc(sizeof(MCstring)*count);
  201.       tptr = args[1];
  202.       lastptr = tptr;
  203.       while (1){
  204.     if (*tptr == '\n' || *tptr == '\0'){
  205.       if (usekeys == True){
  206.         keyptr = lastptr;
  207.         while(++keyptr < tptr){
  208.           if (*keyptr == ','){
  209.         *keyptr = '\0';
  210.         keys[nelements] = lastptr;
  211.         lastptr = keyptr+1;
  212.         break;
  213.           }
  214.         }
  215.       }
  216.       tstrings[nelements].sptr = lastptr;
  217.       tstrings[nelements].length = tptr - lastptr;
  218.       lastptr = tptr+1;
  219.       nelements++;
  220.       if (*tptr == '\0')
  221.         break;
  222.     }
  223.     tptr++;
  224.       }
  225.       SetArray(args[0],nelements,tstrings,keys,&retvalue);
  226.       free(tstrings);
  227.       if (usekeys == True)
  228.     free(keys);
  229.     }
  230.   if (retstr == NULL)
  231.     retstr = calloc(1, 1);
  232.   *retstring = retstr;
  233. }
  234.  
  235. #ifdef __STDC__
  236. void XGetArray(char *args[], int nargs, char **retstring,
  237.            Bool *pass, Bool *error)
  238. #else
  239. void XGetArray(args, nargs, retstring, pass, error)
  240.      char *args[];
  241.      int nargs;
  242.      char **retstring;
  243.      Bool *pass;
  244.      Bool *error;
  245. #endif
  246. {
  247.   int retvalue;
  248.   char *retstr = NULL;
  249.   MCstring *values = NULL; 
  250.   char **keys = NULL;
  251.   int nelements = 0;
  252.   char *tptr = NULL;
  253.   int size = 0;
  254.   int i;
  255.   *pass = False;
  256.   *error = False;
  257.   GetArray(args[0],&nelements,values,keys,&retvalue);
  258.   if (nelements != 0){
  259.     values = malloc(sizeof(MCstring) * nelements);
  260.     keys = malloc(sizeof(char *) * nelements);
  261.     GetArray(args[0],&nelements,values,keys,&retvalue);
  262.     for (i = 0; i < nelements; i++){
  263.       MCstring *s = &values[i];
  264.       char *key = keys[i];
  265.       int klength = strlen(key);
  266.       tptr = realloc(tptr, size + s->length + 1 + klength + 1);
  267.       memcpy(&tptr[size],key,klength);
  268.       size += klength;
  269.       tptr[size++] = '\t';
  270.       memcpy(&tptr[size],s->sptr,s->length);
  271.       size += s->length;
  272.       tptr[size++] = '\n';
  273.     }
  274.     tptr[--size] = '\0';
  275.     retstr = tptr;
  276.     free(values);
  277.     free(keys);
  278.   }
  279.   if (retstr == NULL)
  280.     retstr = calloc(1, 1);
  281.   *retstring = retstr;
  282. }
  283.  
  284. #define RGBAtoFOUR(r, g, b, a) ((int)(((a) << 24) | ((r) << 16)\
  285.          | ((g) << 8) | (b)))
  286. #define FOURtoB(rgb) ((rgb) & 0xff)
  287. #define FOURtoG(rgb) (((rgb) >> 8) & 0xff)
  288. #define FOURtoR(rgb) (((rgb) >> 16) & 0xff)
  289. #define FOURtoA(rgb) ((rgb) >> 24) 
  290.  
  291. #ifdef __STDC__
  292.     int get255(int n)
  293. #else
  294.     int get255(n)
  295.     int n;
  296. #endif
  297. {
  298.     if (n > 254) return 255;
  299.     if (n < 0) return 0;
  300.     return n;
  301. }
  302.  
  303.      
  304. #ifdef __STDC__
  305.      void XConvolve(char *args[], int nargs, char **retstring,
  306.          Bool *pass, Bool *error)
  307. #else
  308.          void XConvolve(args, nargs, retstring, pass, error)
  309.          char *args[];
  310.      int nargs;
  311.      char **retstring;
  312.      Bool *pass;
  313.      Bool *error;
  314. #endif
  315.      {
  316.          int retvalue;
  317.          *pass = False;
  318.          *error = False;
  319.          if (nargs == 6){
  320.              MCstring image;
  321.              char emp[] = "";
  322.              GetVariableEx(args[0],emp,&image,&retvalue); //get image
  323.              if (image.sptr != NULL){
  324.                  MCstring matrixelement;
  325.                  char *convimage;
  326.                  int convmatrix[3][3];
  327.                  int width,height, bytesperline, scale,i,j;
  328.                  char keybuffer[8];
  329.                  Bool success = True;
  330.                  width = atoi(args[1]);  //argument 2 contains width of image
  331.                  height = atoi(args[2]); //argument 3 contains height of image
  332.                  scale = atoi(args[3]); //get scale for convolution operation
  333.                  bytesperline = image.length/height; //need this info for convolution filter
  334.                  convimage = malloc(image.length); //allocate space for convoluted image (same size as original)
  335.                  for (i = 0; i < 3; i++){ //populate matrix with elements from MC array
  336.                      for (j = 0; j < 3; j++) {
  337.                          sprintf(keybuffer ,"%d,%d", i+1, j+1); //create key (our MC array starts at 1)
  338.                          GetVariableEx(args[4], keybuffer, &matrixelement,&retvalue); //get element from array
  339.                          if (matrixelement.sptr == NULL) { //if not found throw an error
  340.                              *retstring = istrdup("element not found in matrix");
  341.                              success = False;
  342.                              break;
  343.                          }
  344.                          else
  345.                              convmatrix[i][j] = atoi(matrixelement.sptr);
  346.                      }
  347.                  }
  348.                  if (success == True) {
  349.                      MCstring newimage;
  350.                      int x,y;
  351.                      for (y = 1; y < height-2; y++) {
  352.                          int *O = (int *)&convimage[y * bytesperline];
  353.                          int *T = (int *)&image.sptr[(y-1) * bytesperline];
  354.                          int *C = (int *)&image.sptr[(y) * bytesperline];
  355.                          int *B = (int *)&image.sptr[(y+1) * bytesperline];
  356.                          for (x = 1; x < width - 2;x++) {
  357.                              int red = get255 ((
  358.                                  (FOURtoR(T[x-1])*convmatrix[0][0]) + (FOURtoR(T[x])*convmatrix[0][1]) + (FOURtoR(T[x+1])*convmatrix[0][2])
  359.                                  + (FOURtoR(C[x-1])*convmatrix[1][0]) + (FOURtoR(C[x])*convmatrix[1][1]) + (FOURtoR(C[x+1])*convmatrix[1][2])
  360.                                  + (FOURtoR(B[x-1])*convmatrix[2][0]) + (FOURtoR(B[x])*convmatrix[2][1]) + (FOURtoR(B[x+1])*convmatrix[2][2]))/scale);
  361.                              int green = get255 ((
  362.                                  (FOURtoG(T[x-1])*convmatrix[0][0]) + (FOURtoG(T[x])*convmatrix[0][1]) + (FOURtoG(T[x+1])*convmatrix[0][2])
  363.                                  + (FOURtoG(C[x-1])*convmatrix[1][0]) + (FOURtoG(C[x])*convmatrix[1][1]) + (FOURtoG(C[x+1])*convmatrix[1][2])
  364.                                  + (FOURtoG(B[x-1])*convmatrix[2][0]) + (FOURtoG(B[x])*convmatrix[2][1]) + (FOURtoG(B[x+1])*convmatrix[2][2]))/scale);
  365.                              int blue = get255 ((
  366.                                  (FOURtoB(T[x-1])*convmatrix[0][0]) + (FOURtoB(T[x])*convmatrix[0][1]) + (FOURtoB(T[x+1])*convmatrix[0][2])
  367.                                  + (FOURtoB(C[x-1])*convmatrix[1][0]) + (FOURtoB(C[x])*convmatrix[1][1]) + (FOURtoB(C[x+1])*convmatrix[1][2])
  368.                                  + (FOURtoB(B[x-1])*convmatrix[2][0]) + (FOURtoB(B[x])*convmatrix[2][1]) + (FOURtoB(B[x+1])*convmatrix[2][2]))/scale);
  369.                              O[x] = RGBAtoFOUR(red,green,blue,0x00);
  370.                          }
  371.                      }
  372.                      newimage.sptr = convimage; 
  373.                      newimage.length = image.length;
  374.                      SetVariableEx(args[5],"",&newimage,&retvalue); //set value of variable to resulting image
  375.                      *retstring = calloc(1, 1);
  376.                  }
  377.                  free(convimage);
  378.              }
  379.          }
  380.          else
  381.              *retstring = istrdup("must pass 6 arguments");
  382.      }
  383.  
  384. /*
  385.  * Call the c library sprintf with a format and argument string.
  386.  * A more complete routine would include checks on the the validity
  387.  * of the arguments and allow more than one argument to be passed.
  388.  * This routine should actually be an XFCN, since it returns a value.
  389.  */
  390. #ifdef __STDC__
  391. void XCsprintf(char *args[], int nargs, char **retstring,
  392.            Bool *pass, Bool *error)
  393. #else
  394. void XCsprintf(args, nargs, retstring, pass, error)
  395.      char *args[];
  396.      int nargs;
  397.      char **retstring;
  398.      Bool *pass;
  399.      Bool *error;
  400. #endif
  401. {
  402.   fprintf(stderr, "XCsprintf called with nargs %d, arg1 is %s\n",
  403.       nargs, args[0]);
  404.   *pass = False;
  405.   if (nargs != 2) {
  406.     /* only set error to true when a syntax error occurs, as it
  407.        causes the script to stop execution at this point */
  408.     *error = True;
  409.     *retstring = istrdup("printf: must pass 2 arguments");
  410.   }
  411.   else {
  412.     *error = False;
  413.     *retstring = malloc(strlen(args[0]) + strlen(args[1]) + 1);
  414.     sprintf(*retstring, args[0], args[1]);
  415.   }
  416. }
  417.  
  418. /*
  419.  * Call the c library atan2 with the required two arguments.
  420.  * A more complete routine would include setting up a matherr
  421.  * routine and checking errno for DOMAIN errors.
  422.  */
  423. #ifdef __STDC__
  424. void XFatan2(char *args[], int nargs, char **retstring,
  425.          Bool *pass, Bool *error)
  426. #else
  427. void XFatan2(args, nargs, retstring, pass, error)
  428.      char *args[];
  429.      int nargs;
  430.      char **retstring;
  431.      Bool *pass;
  432.      Bool *error;
  433. #endif
  434. {
  435.   fprintf(stderr, "XCatan2 called with nargs %d, arg1 is %s\n",
  436.       nargs, args[0]);
  437.   *pass = False;
  438.   if (nargs != 2) {
  439.     /* only set error to true when a syntax error occurs, as it
  440.        causes the script to stop execution at this point */
  441.     *error = True;
  442.     *retstring = istrdup("atan2: must pass 2 arguments");
  443.   }
  444.   else {
  445.     *error = False;
  446.     *retstring = malloc(16);
  447.     sprintf(*retstring, "%G", atan2(atof(args[0]), atof(args[1])));
  448.   }
  449. }
  450.  
  451. /*
  452.  * Call back into MetaCard and get or set the contents of the
  453.  * objects specified in the argument list.
  454.  */
  455. #ifdef __STDC__
  456. void XCcallbacktests(char *args[], int nargs, char **retstring,
  457.              Bool *pass, Bool *error)
  458. #else
  459. void XCcallbacktests(args, nargs, retstring, pass, error)
  460.      char *args[];
  461.      int nargs;
  462.      char **retstring;
  463.      Bool *pass;
  464.      Bool *error;
  465. #endif
  466. {
  467.   int retvalue;
  468.   char buffer[256];
  469.   char *mcstring;
  470. #ifdef MACOS
  471.   unsigned long seconds;
  472. #endif
  473.  
  474. /* activate a card script handler */
  475.   sprintf(buffer, "doSomething %s", args[0]);
  476.   SendCardMessage(buffer, &retvalue);
  477.  
  478. /* tell the engine to execute a command */
  479. #ifndef MACOS
  480.   sprintf(buffer, "put \"Message time %d\" into field %s",
  481.       (int)time(NULL), args[1]);
  482. #else  //MAC platform
  483.   GetDateTime(&seconds);
  484.   sprintf(buffer, "put \"Message time %d\" into field %s",
  485.       (int)seconds, args[1]);
  486. #endif     
  487.   SendMCMessage(buffer, &retvalue);
  488.  
  489. /* get a global, tell MC to add 1 to the result, then set the global */
  490.   mcstring = GetGlobal(args[2], &retvalue);
  491.   sprintf(buffer, "%s + 1", mcstring);
  492.   free(mcstring);
  493.   mcstring = EvalExpr(buffer, &retvalue);
  494.   SetGlobal(args[2], mcstring, &retvalue);
  495.   free(mcstring);
  496.  
  497. /* The first parameter to field routines should be:
  498.    "true" to look for the field on the card,
  499.    "false" to look only on the background,
  500.    "" to look on both the card and the background
  501.    or a group name to look for the field in that group. */
  502.  
  503.   mcstring = GetFieldByName("", args[3], &retvalue);
  504.   SetFieldByName("", args[6], mcstring, &retvalue);
  505.   free(mcstring);
  506.  
  507.   mcstring = GetFieldByNum("", atoi(args[4]), &retvalue);
  508.   SetFieldByNum("", atoi(args[7]), mcstring, &retvalue);
  509.   free(mcstring);
  510.   
  511.   mcstring = GetFieldById("", atoi(args[5]), &retvalue);
  512.   SetFieldById("", atoi(args[8]), mcstring, &retvalue);
  513.   free(mcstring);
  514.  
  515. /* get an expression from a local variable, evaluate the expression
  516.    in the local context, and put the value back into the local variable */
  517.   mcstring = GetVariable(args[9], &retvalue);
  518.   strcpy(buffer, mcstring);
  519.   free(mcstring);
  520.   mcstring = EvalExpr(buffer, &retvalue);
  521.   SetVariable(args[9], mcstring, &retvalue);
  522.   free(mcstring);
  523.  
  524.   *pass = False;
  525.   *error = False;
  526.   *retstring = istrdup("callbacktest done");
  527. }
  528.  
  529. /*
  530.  * Do one generation of the life simulation, coloring the squares
  531.  * for each of the live cells.  This function is called at on the
  532.  * idle event, the rate of which is controlled by the X_set_idle_rate
  533.  * function, which is called in the XClife_delay function.
  534.  */
  535. void life_generation()
  536. {
  537.   int retvalue; 
  538.   int x, y;
  539.  
  540. #ifdef X11
  541.   if (pm == 0)
  542.     return;
  543. #elif defined WIN32
  544.   if (bm == NULL)
  545.     return;
  546. #elif defined MACOS
  547.   if (gw == NULL)
  548.     return;
  549. #endif
  550.   if (oldgrid == g1) {
  551.     oldgrid = g2;
  552.     newgrid = g1;
  553.   }
  554.   else {
  555.     oldgrid = g1;
  556.     newgrid = g2;
  557.   }
  558.   for (x = 1 ; x <= GRID_SIZE ; x++) {
  559.     for (y = 1 ; y <= GRID_SIZE ; y++) {
  560.       int neighbors = oldgrid[x - 1][y - 1] + oldgrid[x][y - 1]
  561.     + oldgrid[x + 1][y - 1] + oldgrid[x - 1][y] + oldgrid[x + 1][y]
  562.     + oldgrid[x - 1][y + 1] + oldgrid[x][y + 1] + oldgrid[x + 1][y + 1];
  563.       if (neighbors == 2)
  564.     newgrid[x][y] = oldgrid[x][y];
  565.       else {
  566.     if (neighbors == 3)
  567.       newgrid[x][y] = 1;
  568.     else
  569.       newgrid[x][y] = 0;
  570. #ifdef X11
  571.     if (newgrid[x][y] != oldgrid[x][y]) {
  572.       if (newgrid[x][y])
  573.         XSetForeground(MCdpy, gc, livecolor);
  574.       else
  575.         XSetForeground(MCdpy, gc, deadcolor);
  576.       XFillRectangle(MCdpy, pm, gc, (x - 1) * CELL_SIZE + 1,
  577.              (y - 1) * CELL_SIZE + 1,
  578.              CELL_SIZE - 2, CELL_SIZE - 2);
  579.     }
  580. #elif defined WIN32
  581.         SelectObject(memhdc, bm);
  582.         if (newgrid[x][y] != oldgrid[x][y]) {
  583.       if (newgrid[x][y]) {
  584.         SelectObject(memhdc,livebrush);
  585.             SelectObject(memhdc, GetStockObject(NULL_PEN));
  586.       }
  587.       else {
  588.         SelectObject(memhdc, deadbrush);
  589.             SelectObject(memhdc, GetStockObject(NULL_PEN));
  590.       }
  591.       Rectangle(memhdc, (x - 1) * CELL_SIZE + 1, (y - 1) * CELL_SIZE + 1,
  592.             (x -1) * CELL_SIZE + 1 + (CELL_SIZE - 2), 
  593.             (y - 1) * CELL_SIZE + 1 + (CELL_SIZE - 2));
  594.     }
  595.         SelectObject(memhdc, oldbrush);
  596.     SelectObject(memhdc, oldbitmap);
  597. #elif defined MACOS
  598.         GetGWorld(&oldport, &olddevice);
  599.           SetGWorld(gw, NULL);
  600.         if (newgrid[x][y] != oldgrid[x][y]) {
  601.       if (newgrid[x][y])
  602.             RGBForeColor(&livecolor);
  603.           else
  604.             RGBForeColor(&deadcolor);
  605.           SetRect(&rect, (x - 1) * CELL_SIZE + 1, (y - 1) * CELL_SIZE + 1,
  606.                    (x -1) * CELL_SIZE + 1 + (CELL_SIZE - 2), 
  607.            (y - 1) * CELL_SIZE + 1 + (CELL_SIZE - 2));
  608.           PaintRect(&rect); 
  609.           SetGWorld(oldport, olddevice);
  610.         }
  611. #endif
  612.       }
  613.     }
  614.   }
  615.   ShowImageByNum("", 1, &retvalue);
  616. }
  617.  
  618. /*
  619.  * Create pixmap and clear it, then set imagePixmapId property.
  620.  * Get GC and colors used for drawing cells.  Put some live cells
  621.  * in at random.
  622.  */
  623. #ifdef __STDC__
  624. void XFlife_init(char *args[], int nargs, char **retstring,
  625.          Bool *pass, Bool *error)
  626. #else
  627. void XFlife_init(args, nargs, retstring, pass, error)
  628.      char *args[];
  629.      int nargs;
  630.      char **retstring;
  631.      Bool *pass;
  632.      Bool *error;
  633. #endif
  634. {
  635.   int x, y;
  636.   X_set_idle_handler(life_generation);
  637.   for (x = 1 ; x <= GRID_SIZE ; x++)
  638.     for (y = 1 ; y <= GRID_SIZE ; y++)
  639.       if (rand() > RAND_MAX / 2)
  640.     g1[x][y] = 1;
  641.   *pass = False;
  642.   *error = False;
  643.   *retstring = malloc(16);
  644. #ifdef X11
  645.   {
  646.     XColor c;
  647.     XWindowAttributes xwa;
  648.     int size = GRID_SIZE * CELL_SIZE;
  649.     XGetWindowAttributes(MCdpy, MCwin, &xwa);
  650.     pm = XCreatePixmap(MCdpy, MCwin, size, size, xwa.depth);
  651.     gc = DefaultGCOfScreen(xwa.screen);
  652.     XAllocNamedColor(MCdpy, xwa.colormap, "red", &c, &c);
  653.     livecolor = c.pixel;
  654.     XAllocNamedColor(MCdpy, xwa.colormap, "gray", &c, &c);
  655.     deadcolor = c.pixel;
  656.     XSetForeground(MCdpy, gc, deadcolor);
  657.     XFillRectangle(MCdpy, pm, gc, 0, 0, GRID_SIZE * CELL_SIZE,
  658.            GRID_SIZE * CELL_SIZE);
  659.     sprintf(*retstring, "%ld", pm);
  660.   }
  661. #elif defined WIN32
  662.   {
  663.     int size = GRID_SIZE * CELL_SIZE;
  664.     HDC winhdc = GetDC(HWND_DESKTOP);
  665.     memhdc = CreateCompatibleDC(winhdc);
  666.     if ((bm = CreateCompatibleBitmap(winhdc, size, size)) == NULL) //compatible to screen
  667.       return;
  668.     ReleaseDC(NULL, winhdc);
  669.     livebrush = CreateSolidBrush(RGB(255, 0, 0));
  670.     deadbrush = CreateSolidBrush(RGB(128, 128, 128)); // Create a gray brush.
  671.    // deadbrush = CreateSolidBrush(RGB(0, 255, 0)); //green
  672.     oldbitmap = SelectObject(memhdc, bm);      //select bitmap into memory DC
  673.     oldbrush = SelectObject(memhdc, deadbrush); 
  674.     if (!Rectangle(memhdc, 0, 0, size, size))
  675.       return;
  676.     SelectObject(memhdc, oldbitmap);
  677.     SelectObject(memhdc, oldbrush);
  678.     sprintf(*retstring, "%ld", bm);
  679.   }
  680. #elif defined MACOS
  681.   {
  682.   
  683.     QDErr err;
  684.     short devdepth;
  685.     GDHandle hgraf;
  686.     PixMapHandle hpixmap;
  687.     SetRect(&rect, 0, 0, GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE);
  688.     hgraf = GetMainDevice();  //get main screen graphic device handle
  689.     HLock((Handle)hgraf);
  690.     hpixmap = ((GDPtr)*hgraf)->gdPMap;
  691.     HLock((Handle)hpixmap);
  692.     devdepth = ((PixMapPtr)*hpixmap)->pixelSize;//get main screen device depth
  693.     HUnlock((Handle)hpixmap);
  694.     HUnlock((Handle)hgraf);
  695.     err = NewGWorld(&gw, devdepth, &rect, NULL, NULL, 0);
  696.     if ((gw == NULL) || (err != noErr))
  697.       return;
  698.     GetGWorld(&oldport, &olddevice);
  699.     SetGWorld(gw, NULL);
  700.     deadcolor.red = deadcolor.green = deadcolor.blue = 32768; // = 128 color gray
  701.     livecolor.red = 65535;        // = 256 color red
  702.     livecolor.green = livecolor.blue = 0;
  703.     RGBForeColor(&deadcolor);
  704.     PaintRect(&rect);
  705.     SetGWorld(oldport, olddevice);
  706.     sprintf(*retstring, "%ld", gw); //return the GWorld created to the calling program
  707.   }
  708. #endif
  709. }
  710.  
  711. /*
  712.  * Set the cell at the x,y coordinate specified to the "live" state.
  713.  */
  714. #ifdef __STDC__
  715. void XClife_create(char *args[], int nargs, char **retstring,
  716.            Bool *pass, Bool *error)
  717. #else
  718. void XClife_create(args, nargs, retstring, pass, error)
  719.      char *args[];
  720.      int nargs;
  721.      char **retstring;
  722.      Bool *pass;
  723.      Bool *error;
  724. #endif
  725. {
  726.  int x, y;
  727.   x = atoi(args[0]) / CELL_SIZE + 1;
  728.   y = atoi(args[1]) / CELL_SIZE + 1;
  729.   newgrid[x][y] = 1;
  730.  
  731. #if defined X11
  732.   XSetForeground(MCdpy, gc, livecolor);
  733.   XFillRectangle(MCdpy, pm, gc, (x - 1) * CELL_SIZE + 1,
  734.          (y - 1) * CELL_SIZE + 1,
  735.          CELL_SIZE - 2, CELL_SIZE - 2);
  736. #elif defined WIN32
  737.   SelectObject(memhdc,livebrush);
  738.   SelectObject(memhdc, GetStockObject(NULL_PEN));
  739.   SelectObject (memhdc, bm);
  740.   Rectangle(memhdc, (x - 1) * CELL_SIZE + 1, (y - 1) * CELL_SIZE + 1,
  741.         (x - 1) * CELL_SIZE + 1 + (CELL_SIZE - 2), 
  742.         (y - 1) * CELL_SIZE + 1 + (CELL_SIZE - 2));
  743.   SelectObject(memhdc, oldbrush);
  744.   SelectObject(memhdc, oldbitmap);
  745. #elif defined MACOS
  746.   GetGWorld(&oldport, &olddevice);
  747.   SetGWorld(gw, NULL);
  748.   RGBForeColor(&livecolor);
  749.   SetRect(&rect, (x - 1) * CELL_SIZE + 1, (y - 1) * CELL_SIZE + 1, 
  750.           (x - 1) * CELL_SIZE + 1 + (CELL_SIZE - 2), (y - 1) * CELL_SIZE + 1 + (CELL_SIZE - 2));
  751.   PaintRect(&rect);
  752.   SetGWorld(oldport, olddevice);
  753. #endif
  754.   *pass = False;
  755.   *error = False;
  756.   *retstring = calloc(1, 1);
  757. }
  758.  
  759. /*
  760.  * Set the delay between generations
  761.  */
  762. #ifdef __STDC__
  763. void XClife_delay(char *args[], int nargs, char **retstring,
  764.            Bool *pass, Bool *error)
  765. #else
  766. void XClife_delay(args, nargs, retstring, pass, error)
  767.      char *args[];
  768.      int nargs;
  769.      char **retstring;
  770.      Bool *pass;
  771.      Bool *error;
  772. #endif
  773. {
  774.   X_set_idle_rate(atoi(args[0]));
  775.   *pass = False;
  776.   *error = False;
  777.   *retstring = calloc(1, 1);
  778. }
  779.  
  780. /*
  781.  * Stop life
  782.  */
  783. #ifdef __STDC__
  784. void XClife_cease(char *args[], int nargs, char **retstring,
  785.            Bool *pass, Bool *error)
  786. #else
  787. void XClife_cease(args, nargs, retstring, pass, error)
  788.      char *args[];
  789.      int nargs;
  790.      char **retstring;
  791.      Bool *pass;
  792.      Bool *error;
  793. #endif
  794. {
  795.  
  796. #ifdef X11
  797.   XWindowAttributes xwa;
  798.   XGetWindowAttributes(MCdpy, MCwin, &xwa);
  799.   XSync(MCdpy, False);                /* make sure all drawing is done */
  800.   XFreeColors(MCdpy, xwa.colormap, &livecolor, 1, 0);
  801.   XFreeColors(MCdpy, xwa.colormap, &deadcolor, 1, 0);
  802.   XFreePixmap(MCdpy, pm);
  803.   pm = 0;
  804. #elif defined WIN32
  805.   DeleteObject(bm);
  806.   bm = NULL;
  807.   DeleteObject(livebrush);
  808.   DeleteObject(deadbrush);
  809.   DeleteDC(memhdc);
  810. #elif defined MACOS
  811.   if (gw != NULL){
  812.     DisposeGWorld(gw);
  813.        gw = NULL;
  814.    }
  815. #endif
  816.   *pass = False;
  817.   *error = False;
  818.   *retstring = calloc(1, 1);
  819. }
  820.  
  821. void XCabort()
  822. {
  823.   fprintf(stderr, "external abort");
  824. }
  825.  
  826. #ifdef X11
  827. #ifdef __STDC__
  828. void main(int argc, char *argv[], char *envp[])
  829. #else
  830. void main(argc, argv, envp)
  831.      int argc;
  832.      char *argv[];
  833.      char *envp[];
  834. #endif
  835. {
  836.   int retval;
  837.   fprintf(stderr, "external startup\n");
  838.   if (!X_init(argc, argv, envp, Xtable, Xname))
  839.     exit(-1);
  840.   X_main_loop();
  841.   retval = X_close();
  842.   fprintf(stderr, "external exit\n");
  843.   exit(retval);
  844. }
  845. #endif
  846.